﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Windows.Forms;
using HalconDotNet;
using Go;

namespace fhs
{
    abstract class CalibAction
    {
        static public string msgView;
        static private generator _action;

        static public bool IsRun()
        {
            return null != _action;
        }

        static public void MakeAction(generator.action action, Action completedHandler, Action<bool> suspendHandler)
        {
            if (IsRun() || StepAction.IsRun() || AutoAction.IsRun())
            {
                return;
            }
            _action = generator.tgo(GlobalData.mainStrand, action, delegate ()
            {
                _action = null;
                msgView = "标定完成";
                completedHandler?.Invoke();
            }, suspendHandler);
        }

        static public void Stop()
        {
            _action?.stop();
        }

        static public void Pause()
        {
            _action?.suspend();
        }

        static public void Resume()
        {
            _action?.resume();
        }

        static public async Task CalibHand(bool isCell, CameraControl[] views, bool[] shows)
        {
            LogMgr.Info($"{(isCell ? "Cell" : "Bl")}手眼标定");
            double firstU = 0;
            VisionName.Camera[] cameras;
            if (isCell)
            {
                cameras = Make.Array(VisionName.Camera.T1Cell, VisionName.Camera.T2Cell, VisionName.Camera.T3Cell, VisionName.Camera.T4Cell);
            }
            else
            {
                cameras = Make.Array(VisionName.Camera.T5Bl, VisionName.Camera.T6Bl, VisionName.Camera.T7Bl, VisionName.Camera.T8Bl);
            }
            tuple<MyPoint, MyPoint[]>[] camera2Robot = new tuple<MyPoint, MyPoint[]>[4];
            generator.children snapChild = new generator.children();
            snapChild.ignore_suspend();
            for (int i = 0; i < camera2Robot.Length; i++)
            {
                MyPoint[] marks = new MyPoint[cameras.Length];
                while (true)
                {
                    msgView = $"开始第{i + 1}点";
                    for (int j = 0; j < cameras.Length; j++)
                    {
                        if (!shows[j])
                        {
                            continue;
                        }
                        int cameraIdx = j;
                        snapChild.go(async delegate ()
                        {
                            while (true)
                            {
                                generator.lock_shield();
                                await VisionMgr.visions[VisionName.Vision.Calib].Translate(views[cameraIdx], null, VisionMgr.visionParams[VisionName.Vision.Calib], new Vision_Mark.Option { camera = cameras[cameraIdx] });
                                await generator.unlock_shield();
                                await generator.sleep(100);
                            }
                        });
                    }
                    await generator.pause_self();
                    await snapChild.stop();
                    bool hasError = false;
                    for (int j = 0; j < cameras.Length; j++)
                    {
                        if (!shows[j])
                        {
                            continue;
                        }
                        int cameraIdx = j;
                        snapChild.go(async delegate ()
                        {
                            generator.lock_shield();
                            Vision_Mark.Result result = (Vision_Mark.Result)await VisionMgr.visions[VisionName.Vision.Calib].Translate(views[4 + cameraIdx], null, VisionMgr.visionParams[VisionName.Vision.Calib], new Vision_Mark.Option { camera = cameras[cameraIdx] });
                            await generator.unlock_shield();
                            if (null != result && !result.error)
                            {
                                marks[cameraIdx] = result.markEx;
                                if (0 == i)
                                {
                                    HTuple width, height;
                                    HOperatorSet.GetImageSize(result.image, out width, out height);
                                    await generator.send_task(() => File.WriteAllLines($"./CalibData/{cameras[cameraIdx]}Size.txt", Make.Array(width.I.ToString(), height.I.ToString())));
                                }
                            }
                            else
                            {
                                hasError = true;
                            }
                        });
                    }
                    await snapChild.wait_all();
                    if (!hasError)
                    {
                        break;
                    }
                    msgView = $"第{i+1}点获取失败，重试";
                    await generator.sleep(1000);
                }
                double currU = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.机械手U]) / GlobalData.轴比例.U;
                if (0 == i)
                {
                    firstU = currU;
                }
                else if (Math.Abs(currU - firstU) > 0.001)
                {
                    await generator.send_control(MainForm.obj, () => MessageBox.Show("U轴在移动过程中发生旋转，停止后重试"));
                    await generator.hold();
                }
                camera2Robot[i] = tuple.make(new MyPoint
                    {
                        X = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.机械手X]) / GlobalData.轴比例.X,
                        Y = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.机械手Y]) / GlobalData.轴比例.Y
                    }, marks);
                LogMgr.Info($"RobotX: {camera2Robot[i].value1.X}, RobotY: {camera2Robot[i].value1.Y}");
                await generator.sleep(1000);
            }
            for (int i = 0; i < cameras.Length; i++)
            {
                if (!shows[i])
                {
                    continue;
                }
                FlatCalib CameraCalibRobot = new FlatCalib();
                CameraCalibRobot.BeginCalib();
                for (int j = 0; j < camera2Robot.Length; j++)
                {
                    CameraCalibRobot.Append(camera2Robot[j].value2[i] - camera2Robot[0].value2[i], camera2Robot[j].value1 - camera2Robot[0].value1);
                }
                CameraCalibRobot.EndCalib();
                await generator.send_task(() => CameraCalibRobot.Save($"./CalibData/{cameras[i]}CalibRobot.txt"));
                LogMgr.Info($"标定残差，{cameras[i]}:{CameraCalibRobot.Residual()}mm");
            }
            await generator.send_task(delegate ()
            {
                string[] productPaths = Directory.GetDirectories("./Product/Config");
                foreach (string productPath in productPaths)
                {
                    DirectOpt.RemoveDirectory($"{productPath}/ProductCalib");
                }
            });
        }

        static public async Task RotateCalib(bool global, bool isCell, CameraControl[] views, bool[] shows)
        {
            string product = ProductMgr.currProduct;
            Dictionary<VisionName.Camera, FlatCalib> camerasCalib = new Dictionary<VisionName.Camera, FlatCalib>();
            bool rotateNeg = await generator.send_task(() => DefaultLoad.Load(false, "./Config/RotateNeg.txt", 0));
            foreach (var item in CameraMgr.cameras)
            {
                FlatCalib calib = new FlatCalib();
                await generator.send_task(() => calib.Load($@".\CalibData\{item.Key}CalibRobot.txt"));
                camerasCalib[item.Key] = calib;
            }
            string calibPath = global ? $"./CalibData" : $"./Product/Config/{product}/ProductCalib";
            await generator.send_task(() => Directory.CreateDirectory(calibPath));
            VisionName.Camera[] cameras;
            string type = isCell ? "Cell" : "Bl";
            if (isCell)
            {
                cameras = Make.Array(VisionName.Camera.T1Cell, VisionName.Camera.T2Cell, VisionName.Camera.T3Cell, VisionName.Camera.T4Cell);
            }
            else
            {
                cameras = Make.Array(VisionName.Camera.T5Bl, VisionName.Camera.T6Bl, VisionName.Camera.T7Bl, VisionName.Camera.T8Bl);
            }
            MyPoint[][] marks = new MyPoint[3][];
            MyPoint[] robotXY = new MyPoint[3];
            double[] robotU = new double[3];
            generator.children snapChild = new generator.children();
            snapChild.ignore_suspend();
            for (int i = 0; i < 3; i++)
            {
                marks[i] = new MyPoint[cameras.Length];
                while (true)
                {
                    msgView = $"{type}相机旋转标定角度点{i + 1}";
                    for (int j = 0; j < cameras.Length; j++)
                    {
                        if (!shows[j])
                        {
                            continue;
                        }
                        int cameraIdx = j;
                        snapChild.go(async delegate ()
                        {
                            while (true)
                            {
                                generator.lock_shield();
                                await VisionMgr.visions[VisionName.Vision.Calib].Translate(views[cameraIdx], null, VisionMgr.visionParams[VisionName.Vision.Calib], new Vision_Mark.Option { camera = cameras[cameraIdx] });
                                await generator.unlock_shield();
                                await generator.sleep(100);
                            }
                        });
                    }
                    await generator.pause_self();
                    await snapChild.stop();
                    bool hasError = false;
                    for (int j = 0; j < cameras.Length; j++)
                    {
                        if (!shows[j])
                        {
                            continue;
                        }
                        int cameraIdx = j;
                        snapChild.go(async delegate ()
                        {
                            generator.lock_shield();
                            Vision_Mark.Result result = (Vision_Mark.Result)await VisionMgr.visions[VisionName.Vision.Calib].Translate(views[4 + cameraIdx], null, VisionMgr.visionParams[VisionName.Vision.Calib], new Vision_Mark.Option { camera = cameras[cameraIdx] });
                            await generator.unlock_shield();
                            if (null != result && !result.error)
                            {
                                marks[i][cameraIdx] = result.markEx;
                            }
                            else
                            {
                                hasError = true;
                            }
                        });
                    }
                    await snapChild.wait_all();
                    if (!hasError)
                    {
                        break;
                    }
                    msgView = $"{type}第{i + 1}点获取失败，重试";
                    await generator.pause_self();
                }
                robotXY[i] = new MyPoint
                {
                    X = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.机械手X]) / GlobalData.轴比例.X,
                    Y = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.机械手Y]) / GlobalData.轴比例.Y
                };
                robotU[i] = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.机械手U]) / (rotateNeg ? -GlobalData.轴比例.U : GlobalData.轴比例.U);
                LogMgr.Info($"RobotX: {robotXY[i].X}, RobotY: {robotXY[i].Y}, RobotU: {robotU[i]}");
                if (i > 0)
                {
                    if ((robotXY[i] - robotXY[0]).Mod > 0.001)
                    {
                        msgView = $"{type}第{i + 1}点旋转时有XY移动，停止后重试";
                        return;
                    }
                }
                await generator.sleep(2000);
            }
            MyPoint[] centers = new MyPoint[cameras.Length];
            for (int i = 0; i < cameras.Length; i++)
            {
                if (!shows[i])
                {
                    continue;
                }
                MyPoint center1 = FlatCalib.RotateCenterAng(camerasCalib[cameras[i]].Trans(marks[0][i]), camerasCalib[cameras[i]].Trans(marks[1][i]), robotU[1] - robotU[0]);
                MyPoint center2 = FlatCalib.RotateCenterAng(camerasCalib[cameras[i]].Trans(marks[1][i]), camerasCalib[cameras[i]].Trans(marks[2][i]), robotU[2] - robotU[1]);
                centers[i] = 0.5 * (center1 + center2);
                LogMgr.Info($"{cameras[i]}两次中心误差 {(center1 - center2).Mod}mm");
                await generator.send_task(() => File.WriteAllLines($"{calibPath}/{cameras[i]}Center.txt", Make.Array(centers[i].X.ToString(), centers[i].Y.ToString())));
                await generator.send_task(() => File.WriteAllLines($"{calibPath}/{cameras[i]}CenterRobot.txt", Make.Array(robotXY[0].X.ToString(), robotXY[0].Y.ToString())));
                MyPoint cameraAxis = default(MyPoint);
                switch (cameras[i])
                {
                    case VisionName.Camera.T1Cell:
                    case VisionName.Camera.T4Cell:
                        cameraAxis = new MyPoint
                        {
                            X = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.Cell相机轴X2]) / GlobalData.轴比例.CellX2,
                            Y = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.Cell相机轴Y]) / GlobalData.轴比例.CellY
                        };
                        break;
                    case VisionName.Camera.T5Bl:
                    case VisionName.Camera.T8Bl:
                        cameraAxis = new MyPoint
                        {
                            X = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.BL相机轴X2]) / GlobalData.轴比例.BlX2,
                            Y = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.BL相机轴Y]) / GlobalData.轴比例.BlY
                        };
                        break;
                    case VisionName.Camera.T2Cell:
                    case VisionName.Camera.T3Cell:
                        cameraAxis = new MyPoint
                        {
                            X = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.Cell相机轴X1]) / GlobalData.轴比例.CellX1,
                            Y = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.Cell相机轴Y]) / GlobalData.轴比例.CellY
                        };
                        break;
                    case VisionName.Camera.T6Bl:
                    case VisionName.Camera.T7Bl:
                        cameraAxis = new MyPoint
                        {
                            X = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.BL相机轴X1]) / GlobalData.轴比例.BlX1,
                            Y = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.BL相机轴Y]) / GlobalData.轴比例.BlY
                        };
                        break;
                }
                double feedIn = (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.入料轴]) / GlobalData.轴比例.FeedIn;
                await generator.send_task(() => File.WriteAllLines($"{calibPath}/{cameras[i]}CenterAxis.txt", Make.Array(cameraAxis.X.ToString(), cameraAxis.Y.ToString())));
                await generator.send_task(() => File.WriteAllLines($"{calibPath}/{cameras[i]}CenterFeedIn.txt", Make.Array(feedIn.ToString())));
                LogMgr.Info($"{cameras[i]}, FeedIn: {feedIn}, AxisX: {cameraAxis.X}, AxisY: {cameraAxis.Y}");
            }
            await generator.send_task(delegate ()
            {
                string[] productPaths = Directory.GetDirectories("./Product/Config");
                foreach (string productPath in productPaths)
                {
                    DirectOpt.RemoveDirectory($"{productPath}/ProductCalib");
                }
            });
            for (int i = 0; i < cameras.Length; i++)
            {
                if (!shows[i])
                {
                    continue;
                }
                for (int j = 0; j < cameras.Length; j++)
                {
                    if (!shows[j] || i == j)
                    {
                        continue;
                    }
                    await generator.send_task(delegate ()
                    {
                        MyPoint markA = camerasCalib[cameras[i]].Trans(marks[0][i]) - centers[i];
                        MyPoint markB = camerasCalib[cameras[j]].Trans(marks[0][j]) - centers[j];
                        LogMgr.Info($"{cameras[i]}-{cameras[j]} Mark距离 {(markA - markB).Mod.ToString("0.00")}mm");
                    });
                }
            }
        }

        static public async Task CameraAxisCalib(bool isCell, CameraControl[] views, bool[] shows)
        {
            VisionName.Camera[] cameras;
            if (isCell)
            {
                cameras = Make.Array(VisionName.Camera.T1Cell, VisionName.Camera.T2Cell, VisionName.Camera.T3Cell, VisionName.Camera.T4Cell);
            }
            else
            {
                cameras = Make.Array(VisionName.Camera.T5Bl, VisionName.Camera.T6Bl, VisionName.Camera.T7Bl, VisionName.Camera.T8Bl);
            }
            tuple<double, double, double, MyPoint[]>[] camera2Robot = new tuple<double, double, double, MyPoint[]>[4];
            generator.children snapChild = new generator.children();
            snapChild.ignore_suspend();
            for (int i = 0; i < camera2Robot.Length; i++)
            {
                MyPoint[] marks = new MyPoint[cameras.Length];
                while (true)
                {
                    msgView = $"开始第{i + 1}点";
                    for (int j = 0; j < cameras.Length; j++)
                    {
                        if (!shows[j])
                        {
                            continue;
                        }
                        int cameraIdx = j;
                        snapChild.go(async delegate ()
                        {
                            while (true)
                            {
                                generator.lock_shield();
                                await VisionMgr.visions[VisionName.Vision.Calib].Translate(views[cameraIdx], null, VisionMgr.visionParams[VisionName.Vision.Calib], new Vision_Mark.Option { camera = cameras[cameraIdx] });
                                await generator.unlock_shield();
                                await generator.sleep(100);
                            }
                        });
                    }
                    await generator.pause_self();
                    await snapChild.stop();
                    bool hasError = false;
                    for (int j = 0; j < cameras.Length; j++)
                    {
                        if (!shows[j])
                        {
                            continue;
                        }
                        int cameraIdx = j;
                        snapChild.go(async delegate ()
                        {
                            generator.lock_shield();
                            Vision_Mark.Result result = (Vision_Mark.Result)await VisionMgr.visions[VisionName.Vision.Calib].Translate(views[4 + cameraIdx], null, VisionMgr.visionParams[VisionName.Vision.Calib], new Vision_Mark.Option { camera = cameras[cameraIdx] });
                            await generator.unlock_shield();
                            if (null != result && !result.error)
                            {
                                marks[cameraIdx] = result.markEx;
                            }
                            else
                            {
                                hasError = true;
                            }
                        });
                    }
                    await snapChild.wait_all();
                    if (!hasError)
                    {
                        break;
                    }
                    msgView = $"第{i + 1}点获取失败，重试";
                    await generator.sleep(1000);
                }
                await generator.sleep(2000);
                if (isCell)
                {
                    camera2Robot[i] = tuple.make(
                        (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.Cell相机轴X1]) / GlobalData.轴比例.CellX1,
                        (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.Cell相机轴X2]) / GlobalData.轴比例.CellX2,
                        (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.Cell相机轴Y]) / GlobalData.轴比例.CellY, marks);
                    LogMgr.Info($"Cell Camera Axis X1: {camera2Robot[i].value1}, Cell Camera Axis X2: {camera2Robot[i].value2}, Cell Camera Axis Y: {camera2Robot[i].value3}");
                }
                else
                {
                    camera2Robot[i] = tuple.make(
                        (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.BL相机轴X1]) / GlobalData.轴比例.BlX1,
                        (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.BL相机轴X2]) / GlobalData.轴比例.BlX2,
                        (int)await CmdName.mc.Read32(CmdName.mcs[CmdName.MC.BL相机轴Y]) / GlobalData.轴比例.BlY, marks);
                    LogMgr.Info($"BL Camera Axis X1: {camera2Robot[i].value1}, BL Camera Axis X2: {camera2Robot[i].value2}, BL Camera Axis Y: {camera2Robot[i].value3}");
                }
            }
            for (int i = 0; i < cameras.Length; i++)
            {
                if (!shows[i])
                {
                    continue;
                }
                FlatCalib CameraCalibAxis = new FlatCalib();
                CameraCalibAxis.BeginCalib();
                for (int j = 0; j < camera2Robot.Length; j++)
                {
                    MyPoint cameraAxis = default(MyPoint);
                    switch (cameras[i])
                    {
                        case VisionName.Camera.T1Cell:
                        case VisionName.Camera.T4Cell:
                        case VisionName.Camera.T5Bl:
                        case VisionName.Camera.T8Bl:
                            cameraAxis = new MyPoint
                            {
                                X = camera2Robot[j].value2 - camera2Robot[0].value2,
                                Y = camera2Robot[j].value3 - camera2Robot[0].value3
                            };
                            break;
                        case VisionName.Camera.T2Cell:
                        case VisionName.Camera.T3Cell:
                        case VisionName.Camera.T6Bl:
                        case VisionName.Camera.T7Bl:
                            cameraAxis = new MyPoint
                            {
                                X = camera2Robot[j].value1 - camera2Robot[0].value1,
                                Y = camera2Robot[j].value3 - camera2Robot[0].value3
                            };
                            break;
                    }
                    CameraCalibAxis.Append(camera2Robot[j].value4[i] - camera2Robot[0].value4[i], cameraAxis);
                }
                CameraCalibAxis.EndCalib();
                await generator.send_task(() => CameraCalibAxis.Save($"./CalibData/{cameras[i]}CalibAxis.txt"));
                LogMgr.Info($"标定残差，{cameras[i]}:{CameraCalibAxis.Residual()}mm");
            }
            await generator.send_task(delegate ()
            {
                string[] productPaths = Directory.GetDirectories("./Product/Config");
                foreach (string productPath in productPaths)
                {
                    DirectOpt.RemoveDirectory($"{productPath}/ProductCalib");
                }
            });
        }

        static public async Task RepeTest(bool isCell, CameraControl[] views, bool[] shows)
        {
            LogMgr.Info($"{(isCell ? "Cell" : "Bl")}手眼标定");
            VisionName.Camera[] cameras;
            if (isCell)
            {
                cameras = Make.Array(VisionName.Camera.T1Cell, VisionName.Camera.T2Cell, VisionName.Camera.T3Cell, VisionName.Camera.T4Cell);
            }
            else
            {
                cameras = Make.Array(VisionName.Camera.T5Bl, VisionName.Camera.T6Bl, VisionName.Camera.T7Bl, VisionName.Camera.T8Bl);
            }
            Dictionary<VisionName.Camera, FlatCalib> camerasCalib = new Dictionary<VisionName.Camera, FlatCalib>();
            foreach (var item in CameraMgr.cameras)
            {
                FlatCalib calib = new FlatCalib();
                await generator.send_task(() => calib.Load($@".\CalibData\{item.Key}CalibRobot.txt"));
                camerasCalib[item.Key] = calib;
            }
            DateTime now = DateTime.Now;
            string testPath = $"./test_data/Repe_{now.ToString("yyyy-MM-dd HHmmss")}.csv";
            await generator.send_task(delegate ()
            {
                if (!File.Exists(testPath))
                {
                    Directory.CreateDirectory("./test_data");
                    string oneLine = "";
                    for (int i = 0; i < cameras.Length; i++)
                    {
                        if (!shows[i])
                        {
                            continue;
                        }
                        oneLine += $"{cameras[i]}_X,{cameras[i]}_Y, ,";
                    }
                    File.WriteAllLines(testPath, Make.Array(oneLine));
                }
            });
            int count = 0;
            generator.children snapChild = new generator.children();
            snapChild.ignore_suspend();
            while (true)
            {
                msgView = $"{(isCell ? "Cell" : "Bl")}相机验证第{++count}次";
                for (int i = 0; i < cameras.Length; i++)
                {
                    if (!shows[i])
                    {
                        continue;
                    }
                    int cameraIdx = i;
                    snapChild.go(async delegate ()
                    {
                        while (true)
                        {
                            generator.lock_shield();
                            await VisionMgr.visions[VisionName.Vision.Calib].Translate(views[cameraIdx], null, VisionMgr.visionParams[VisionName.Vision.Calib], new Vision_Mark.Option { camera = cameras[cameraIdx] });
                            await generator.unlock_shield();
                            await generator.sleep(100);
                        }
                    });
                }
                await generator.pause_self();
                await snapChild.stop();
                bool hasError = false;
                MyPoint[] marks = new MyPoint[cameras.Length];
                for (int i = 0; i < cameras.Length; i++)
                {
                    if (!shows[i])
                    {
                        continue;
                    }
                    int cameraIdx = i;
                    snapChild.go(async delegate ()
                    {
                        generator.lock_shield();
                        Vision_Mark.Result result = (Vision_Mark.Result)await VisionMgr.visions[VisionName.Vision.Calib].Translate(views[4 + cameraIdx], null, VisionMgr.visionParams[VisionName.Vision.Calib], new Vision_Mark.Option { camera = cameras[cameraIdx] });
                        await generator.unlock_shield();
                        await generator.sleep(100);
                        if (null != result && !result.error)
                        {
                            marks[cameraIdx] = result.markEx;
                        }
                        else
                        {
                            hasError = true;
                        }
                    });
                }
                await snapChild.wait_all();
                if (!hasError)
                {
                    await generator.send_task(delegate ()
                    {
                        string oneLine = "";
                        for (int i = 0; i < cameras.Length; i++)
                        {
                            if (!shows[i])
                            {
                                continue;
                            }
                            MyPoint pt = camerasCalib[cameras[i]].Trans(marks[i]);
                            oneLine += $"{pt.X.ToString("0.000")},{pt.Y.ToString("0.000")}, ,";
                        }
                        File.AppendAllLines(testPath, Make.Array(oneLine));
                        LogMgr.Info(oneLine);
                    });
                }
            }
        }

        static public async Task Monitor(bool isCell, CameraControl[] views, bool[] shows)
        {
            LogMgr.Info($"{(isCell ? "Cell" : "Bl")}监视");
            VisionName.Camera[] cameras;
            if (isCell)
            {
                cameras = Make.Array(VisionName.Camera.T1Cell, VisionName.Camera.T2Cell, VisionName.Camera.T3Cell, VisionName.Camera.T4Cell);
            }
            else
            {
                cameras = Make.Array(VisionName.Camera.T5Bl, VisionName.Camera.T6Bl, VisionName.Camera.T7Bl, VisionName.Camera.T8Bl);
            }
            msgView = $"{(isCell ? "Cell" : "Bl")}监视";
            generator.children snapChild = new generator.children();
            snapChild.ignore_suspend();
            for (int i = 0; i < cameras.Length; i++)
            {
                if (!shows[i])
                {
                    continue;
                }
                int cameraIdx = i;
                snapChild.go(async delegate ()
                {
                    while (true)
                    {
                        generator.lock_shield();
                        await VisionMgr.visions[VisionName.Vision.Calib].Preview(views[cameraIdx], null, VisionMgr.visionParams[VisionName.Vision.Calib], new Vision_Mark.Option { camera = cameras[cameraIdx] });
                        await generator.unlock_shield();
                        await generator.sleep(100);
                    }
                });
            }
            await generator.pause_self();
            await snapChild.stop();
        }
    }
}
